package cn.geminis.lowcode.processor;

import cn.geminis.lowcode.annotation.UuidEntity;
import cn.geminis.lowcode.compiler.code.*;
import cn.geminis.lowcode.utils.Flags;
import cn.geminis.lowcode.utils.Utils;
import com.google.auto.service.AutoService;

import javax.annotation.processing.Processor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author puddi
 */
@AutoService(Processor.class)
@SupportedAnnotationTypes("cn.geminis.lowcode.annotation.UuidEntity")
public class UuidEntityProcessor extends AbstractBaseProcessor {

    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        roundEnv.getElementsAnnotatedWith(UuidEntity.class)
                .forEach(element -> {
                    var entityClass = new LcClass(element);
                    addIdField(entityClass);
                    addSetIdMethod(entityClass);

                    Utils.noteMessage(Utils.getElementQualifiedName(element) + " id Enhanced");
                });

        return true;
    }

    private void addIdField(LcClass entity) {
        var idField = new LcVariable(
                new LcModifier(
                        Flags.PRIVATE,
                        new LcAnnotation("jakarta.persistence.Id"),
                        new LcAnnotation(
                                "jakarta.persistence.Column",
                                Map.of("length", 36)
                        )
                ),
                "String",
                "id"
        );
        entity.append(idField);
    }

    private void addSetIdMethod(LcClass entity) {
        var idSetMethod = new LcMethod(
                new LcModifier(
                        Flags.PRIVATE,
                        new LcAnnotation("jakarta.persistence.PrePersist")
                ),
                "VOID",
                "setId",
                List.of(),
                List.of(),
                List.of(
                        new LcIf(
                                new LcApply("java.util.Objects.isNull", new LcIdent("id")),
                                List.of(
                                        new LcAssign(
                                                "id",
                                                new LcApply(
                                                        List.of(
                                                                new LcApply.InvokeInfo("java.util.UUID.randomUUID"),
                                                                new LcApply.InvokeInfo("toString")
                                                        )
                                                )
                                        ).exec()
                                )
                        )
                )
        );
        entity.append(idSetMethod);
    }
}
